package com.oracle.ateam.atg.test.common;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;

import com.oracle.ateam.atg.test.DustUtils;
import com.oracle.ateam.atg.test.JUnitDustRunner;
import com.oracle.ateam.atg.test.annotations.Component;
import com.oracle.ateam.atg.test.annotations.Modules;

import atg.adapter.gsa.GSARepository;
import atg.servlet.ServletTestUtils.TestingDynamoHttpServletRequest;
import atg.servlet.ServletTestUtils.TestingDynamoHttpServletResponse;
import atg.servlet.ServletUtil;

/**
 * This is a base test class to be extended by individual unit test classes.
 *
 * This base helps setup common items needed for each test, and makes writing
 * individual unit tests easier.
 *
 * @author mshanley
 *
 */
@RunWith(JUnitDustRunner.class)
// Declare the modules you need to start nucleus with. Dependencies will be
// calculated just like starting a normal instance.
@Modules(value = { "DPS", "DCS.CustomCatalogs", "ATeamSample.ATeamCommon" })
public abstract class AbstractCommonTestHelper {

	@Component("/atg/commerce/catalog/ProductCatalog")
	protected static GSARepository productCatalog;

	// priceLists are not actually being used by any tests
	// This is here as an example. Any repository you declare in this base class
	// will become available to all test classes that extend.
	// @Component("/atg/commerce/pricing/PriceLists")
	// protected static GSARepository priceListRepository;

	// this can be used in any class extending this base
	/** Profile Adapter Repository component. */
	@Component("/atg/userprofiling/ProfileAdapterRepository")
	protected static GSARepository profileAdapterRepository;

	/** Site Configuration Repository. */
	@Component("/atg/multisite/SiteRepository")
	protected static GSARepository siteRepository;

	/** Request object for DynamoHttpServletRequest **/
	protected TestingDynamoHttpServletRequest request;

	/** TestingDynamoHttpServletResponse **/
	protected TestingDynamoHttpServletResponse response;

	/** Path to the common multisite site config data */
	private static final String SHARED_SITECONFIG_PATH = "/commonSiteConfig/CommonSiteConfig.xml";

	/**
	 * Can be overridden in extending classed. Using this is optional.
	 *
	 * This is called one time, when the entire test class starts up.
	 *
	 * @throws Exception
	 */
	@BeforeClass
	public static void BeforeClass() throws Exception {

	}

	/**
	 * Can be overridden in extending classed. Using this is optional.
	 *
	 * This is called one time, when the entire test class ends.
	 *
	 * @throws Exception
	 */
	@AfterClass
	public static void AfterClass() throws Exception {

	}

	/**
	 * Called before each individual unit test method is executed.
	 *
	 * @throws Exception
	 */
	@Before
	public final void onCreate() throws Exception {

		// Most scenarios that use DCS require a site to be defined, so load a
		// default site for every test.
		DustUtils.loadRepositoryData(siteRepository, this.getClass().getResource(SHARED_SITECONFIG_PATH));

		// if a specific test class needs to load repo data, it should override
		// the loadRepositoryData method.
		loadRepositoryData();

		// default request object any extneding test can use
		request = DustUtils.createDefaultRequest();
		// default response object any extneding test can use
		response = DustUtils.createResponse();

		ServletUtil.setCurrentRequest(request);
		response.setRequest(request);

		// If you need a profile object, this will create a new anon profile.
		DustUtils.createProfile(request);

		// call setUp, which can be overridden in other classes
		setUp();
	}

	/**
	 * Called after each individual unit test method is executed.
	 *
	 * @throws Exception
	 */
	@After
	public final void onFinish() throws Exception {
		// cleanup and repositories and components registers with the Component
		// annotation.
		// We don't want data to persist between tests.
		DustUtils.cleanAllComponents(this.getClass());

		// Gets a list of all session ID's and removes them.
		// We want fresh session data for each test.
		DustUtils.removeAllSessions();

		// if you created a profile, explicitly remove some components
		// and set the current profile to null.
		DustUtils.removeProfile();

		// call tearDown, which can be overridden in other classes
		tearDown();

	}

	/**
	 * Can be overridden in extending classed. Using this is optional.
	 *
	 * This is where repository XML should be loaded.
	 *
	 * @throws Exception
	 */
	abstract protected void loadRepositoryData() throws Exception;

	/**
	 * Can be overridden in extending classed. Using this is optional.
	 *
	 * Called at the end of our @Before method.
	 *
	 * @throws Exception
	 */
	abstract protected void setUp() throws Exception;

	/**
	 * Can be overridden in extending classed. Using this is optional.
	 *
	 * Called at the end of our @After method.
	 *
	 * @throws Exception
	 */
	abstract protected void tearDown() throws Exception;
}
